#include <stdio.h>
#include <signal.h>
#include "../util/h/iUtil.h"
#include "../util/h/iThread.h"
#include "../util/h/iMsgDB.h"
#include "../util/h/iThreadMgr.h"
#include "../util/h/iTime.h"
#include "../tp/iTPListener.h"
#include "OTCPTester.h"
#include "PBNTester.h"
#include "option.h"
#include "app.h"

bool g_running = true;
uint8_t Application::g_app_module = MOD_RESERVED+1;
void signal_handler(int32_t sig)
{
    if(sig==SIGINT || sig==SIGTERM)
        g_running = false;
}

int main(int argc, char* argv[])
{
    g_optind = 1;
    std::string addr = "TCP://0.0.0.0:2012";
    std::string bind = "0.0.0.0:0";
    while(1)
    {
        int option_index = 0;
        struct option long_options[] = {    {"addr", 1, 0, 0},
                                            {"bind", 1, 0, 0},
                                            {0     , 0, 0, 0} };
        int c = getopt_long(argc, argv, "", long_options, &option_index);
        if(-1 == c)
            break;
        switch(c)
        {
        case 0:
            {
                switch(option_index)
                {
                case 0:
                    {
                        addr = g_optarg;
                    }
                    break;
                case 1:
                    {   
                        bind = g_optarg;
                    }
                    break;
                }
            }
            break;
        }
    }

    char log[255]={0};
    strcpy(log, argv[0]);
	char* log_dir = log;
	char* name = log;
	name += strlen(log);
	while(*name!='\\' && *name!='/'){--name;}
	*name++ = 0;
    INIT_LOGGER(log_dir, name);
    while(iSingleton<iLogger>::instance()->register_module(Application::g_app_module, "APP")==false)
    {
        Application::g_app_module++;
    }

#if defined(__WIN__)
	WORD wVersionRequested;
	WSADATA wsaData;
	int err;
	wVersionRequested = MAKEWORD(2, 2);
	err = WSAStartup(wVersionRequested, &wsaData);
	if (err != 0) {
		printf("WSAStartup failed with error: %d\n", err);
		return 1;
	}
#elif defined(__LINUX__)
    signal(SIGINT,  signal_handler);
    signal(SIGTERM, signal_handler);
    signal(SIGUSR2, signal_handler);
    signal(SIGPIPE, SIG_IGN);
#endif

    iThread* main_thd = iThreadMgr::spawn_this();
	iThreadMgr::spawn_timer();
    char proto[32],ip[64],port[8];
    if(!parse_address(addr.c_str(), proto, ip, port))
        return -1;
#if defined(__SERVER__)
    iTPListener* lsn = iTPListener::new_instance(addr.c_str());
    if(!lsn->listen(strstr(proto, "PKG") ? (iTPListener::iSink*)new PBNTester(NULL) : (iTPListener::iSink*)new OTCPTester(NULL)))
    {
        INFO("listen failed");
        return 0;
    }
	INFO("listen on "<<addr);
#else 
    char local[32]={0};
    sprintf(local, "%s://%s", proto, bind.c_str());
	iTPConnection* conn = iTPConnection::new_instance(addr.c_str(), local);
    iMsgDB* req = iMsgDB::new_instance(NULL, 64*1024-1, 64*1024-1);
	conn->connect_request(  req, 
                            strstr(proto, "PKG") ? (iTPConnection::iSink*)new PBNTester(conn) : (iTPConnection::iSink*)new OTCPTester(NULL));
    INFO("connect to server");
#endif
    
    while(g_running)
    {
        if(0==main_thd->run())
            main_thd->wait(40);
    }

    INFO("Teminated");
}
